home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sprite 1984 - 1993
/
Sprite 1984 - 1993.iso
/
src
/
kernel
/
sys
/
sun3.md
/
sysPrintf.c.old
< prev
Wrap
Text File
|
1992-12-18
|
12KB
|
601 lines
/*
* sysPrintf --
*
* Perform all formatted printing to the console.
*
* This is adapted from _doprnt. It has no comments except those put
* in _doprnt. Should be cleaned up and put into Sprite style. This
* copyright is bogus until we rewrite this routine.
*
* Copyright (C) 1985 Regents of the University of California
* All rights reserved.
*/
#ifndef lint
static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/sys/sun3.md/sysPrintf.c.old,v 9.0 89/09/12 15:20:54 douglis Stable $ SPRITE (Berkeley)";
#endif /* lint */
#include "sprite.h"
#include "mach.h"
#include "sys.h"
#include "dbg.h"
#include "dev.h"
#define NextArg(argList, type) ((type *)(argList += sizeof(type)))[-1]
/* Maximum number of digits in any integer (long) representation */
#define MAXDIGS 11
/* Largest (normal length) positive integer */
#define MAXINT 2147483647
/* A long with only the high-order bit turned on */
#define HIBIT 0x80000000L
/* Convert a digit character to the corresponding number */
#define tonumber(x) ((x)-'0')
/* Convert a number between 0 and 9 to the corresponding digit */
#define todigit(x) ((x)+'0')
/* Data type for flags */
typedef char bool;
#define max(a,b) ((a) > (b) ? (a) : (b))
#define min(a,b) ((a) < (b) ? (a) : (b))
/* If this symbol is nonzero, allow '0' as a flag */
#define FZERO 1
#define emitchar(c) { Dev_SyslogPutChar(c); count++; }
#ifndef lint
/*
* ----------------------------------------------------------------------------
*
* strlen --
*
* Return the length of the string.
*
* Results:
* The length of the string.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
static int
strlen(s)
register char *s;
{
register int n;
n = 0;
while (*s++)
n++;
return (n);
}
/*
* ----------------------------------------------------------------------------
*
* isdigit --
*
* Return true if the character is a digit and false otherwise.
*
* Results:
* True if the character is a digit and false otherwise.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
static int
isdigit(c)
char c;
{
return(c >= '0' && c <= '9');
}
/*
* ----------------------------------------------------------------------------
*
* Sys_DoPrintf --
*
* Perform a C style printf to the monitor. This has all of the
* functionality of a normal C printf except for floating point.
*
* Results:
* Number of characters printed.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
int
Sys_DoPrintf(format, argList)
char *format;
char *argList;
{
/* Current position in format */
char *cp;
/* Starting and ending points for value to be printed */
char *bp, *p;
/* Field width and precision */
int width, prec;
/* Format code */
char fcode;
/* Number of padding zeroes required on the left */
int lzero;
/* Flags - nonzero if corresponding character appears in format */
bool length; /* l */
bool fplus; /* + */
bool fminus; /* - */
bool fblank; /* blank */
bool fsharp; /* # */
bool fzero; /* 0 */
/* Pointer to sign, "0x", "0X", or empty */
char *prefix;
char buf[MAXDIGS];
/* The value being converted, if integer */
long val;
/* Set to point to a translate table for digits of whatever radix */
char *tab;
/* Work variables */
int n, hradix, lowbit;
/* count of output characters */
int count;
cp = format;
count = 0;
/*
* The main loop -- this loop goes through one iteration
* for each ordinary character or format specification.
*/
while (*cp)
if (*cp != '%') {
/* Ordinary (non-%) character */
emitchar(*cp);
cp++;
} else {
/*
* % has been found.
* First, parse the format specification.
*/
/* Scan the <flags> */
fplus = fminus = fblank = fsharp = 0;
#if FZERO
fzero = 0;
#endif
scan: switch (*++cp) {
case '+':
fplus = 1;
goto scan;
case '-':
fminus = 1;
goto scan;
case ' ':
fblank = 1;
goto scan;
case '#':
fsharp = 1;
goto scan;
#if FZERO
case '0':
fzero = 1;
goto scan;
#endif
}
/* Scan the field width */
if (*cp == '*') {
width = NextArg(argList, int);
if (width < 0) {
width = -width;
fminus = 1;
}
cp++;
} else {
width = 0;
while (isdigit(*cp)) {
n = tonumber(*cp++);
width = width * 10 + n;
}
}
/* Scan the precision */
if (*cp == '.') {
/* '*' instead of digits? */
if (*++cp == '*') {
prec = NextArg(argList, int);
cp++;
} else {
prec = 0;
while (isdigit(*cp)) {
n = tonumber(*cp++);
prec = prec * 10 + n;
}
}
} else
prec = -1;
/* Scan the length modifier */
length = 0;
switch (*cp) {
case 'l':
length = 1;
/* No break */
case 'h':
cp++;
}
/*
* The character addressed by cp must be the
* format letter -- there is nothing left for
* it to be.
*
* The status of the +, -, #, blank, and 0
* flags are reflected in the variables
* "fplus", "fminus", "fsharp", "fblank",
* and "fzero", respectively.
* "width" and "prec" contain numbers
* corresponding to the digit strings
* before and after the decimal point,
* respectively. If there was no decimal
* point, "prec" is -1.
*
* The following switch sets things up
* for printing. What ultimately gets
* printed will be padding blanks, a prefix,
* left padding zeroes, a value, right padding
* zeroes, a suffix, and more padding
* blanks. Padding blanks will not appear
* simultaneously on both the left and the
* right. Each case in this switch will
* compute the value, and leave in several
* variables the information necessary to
* construct what is to be printed.
*
* The prefix is a sign, a blank, "0x", "0X",
* or null, and is addressed by "prefix".
*
* The suffix is either null or an exponent,
* and is addressed by "suffix".
*
* The value to be printed starts at "bp"
* and continues up to and not including "p".
*
* "lzero" and "rzero" will contain the number
* of padding zeroes required on the left
* and right, respectively. If either of
* these variables is negative, it will be
* treated as if it were zero.
*
* The number of padding blanks, and whether
* they go on the left or the right, will be
* computed on exit from the switch.
*/
lzero = 0;
prefix = "";
switch (fcode = *cp++) {
/*
* fixed point representations
*
* "hradix" is half the radix for the conversion.
* Conversion is unsigned unless fcode is 'd'.
* HIBIT is 1000...000 binary, and is equal to
* the maximum negative number.
* We assume a 2's complement machine
*/
case 'D':
case 'U':
length = 1;
case 'd':
case 'u':
hradix = 5;
goto fixed;
case 'O':
length = 1;
case 'o':
hradix = 4;
goto fixed;
case 'X':
case 'x':
hradix = 8;
fixed:
/* Establish default precision */
if (prec < 0)
prec = 1;
/* Fetch the argument to be printed */
if (length)
val = NextArg(argList, long);
else if (fcode == 'd')
val = NextArg(argList, int);
else
val = NextArg(argList, unsigned);
/* If signed conversion, establish sign */
if (fcode == 'd' || fcode == 'D') {
if (val < 0) {
prefix = "-";
/*
* Negate, checking in
* advance for possible
* overflow.
*/
if (val != HIBIT)
val = -val;
} else if (fplus)
prefix = "+";
else if (fblank)
prefix = " ";
}
#if FZERO
if (fzero) {
int n = width - strlen(prefix);
if (n > prec)
prec = n;
}
#endif
/* Set translate table for digits */
if (fcode == 'X')
tab = "0123456789ABCDEF";
else
tab = "0123456789abcdef";
/* Develop the digits of the value */
p = bp = buf + MAXDIGS;
while (val) {
lowbit = val & 1;
val = (val >> 1) & ~HIBIT;
*--bp = tab[val % hradix * 2 + lowbit];
val /= hradix;
}
/* Calculate padding zero requirement */
lzero = bp - p + prec;
/* Handle the # flag */
if (fsharp && bp != p)
switch (fcode) {
case 'o':
if (lzero < 1)
lzero = 1;
break;
case 'x':
prefix = "0x";
break;
case 'X':
prefix = "0X";
break;
}
break;
case 'c':
buf[0] = NextArg(argList, int);
bp = &buf[0];
p = bp + 1;
break;
case 's':
bp = NextArg(argList, char *);
if (prec < 0)
prec = MAXINT;
/* avoid *(0) */
if (bp == NULL)
bp = "(null)";
for (n=0; *bp++ != '\0' && n < prec; n++)
;
p = --bp;
bp -= n;
break;
case '\0':
cp--;
break;
/* case '%': */
default:
p = bp = &fcode;
p++;
break;
}
if (fcode != '\0') {
/* Calculate number of padding blanks */
int nblank;
nblank = width
- (p - bp)
- (lzero < 0? 0: lzero)
- strlen(prefix);
/* Blanks on left if required */
if (!fminus)
while (--nblank >= 0)
emitchar(' ');
/* Prefix, if any */
while (*prefix != '\0') {
emitchar(*prefix);
prefix++;
}
/* Zeroes on the left */
while (--lzero >= 0)
emitchar('0');
/* The value itself */
while (bp < p) {
emitchar(*bp);
bp++;
}
/* Blanks on the right if required */
if (fminus)
while (--nblank >= 0)
emitchar(' ');
}
}
return (count);
}
#else /* lint */
/*
* Header just for linting.
*/
/*ARGSUSED*/
int
Sys_DoPrintf(format, argList)
char *format;
char *argList;
{
return 0;
}
#endif /* lint */
Boolean sysPanicing = FALSE;
/*
* ----------------------------------------------------------------------------
*
* Sys_Panic --
*
* Print a formatted string to the monitor and then either abort to the
* debugger or continue depending on the panic level.
*
* Results:
* None.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
/*VARARGS2*/
void
Sys_Panic(level, format, args)
Sys_PanicLevel level;
char *format;
int args;
{
if (level == SYS_WARNING) {
Sys_UnSafePrintf("Warning: ");
} else {
Dev_SyslogDebug(TRUE);
Sys_UnSafePrintf("Fatal Error: ");
}
(void) Sys_DoPrintf(format, (char *) &args);
if (level == SYS_FATAL) {
/*
* Make sure the monitor is enabled.
*/
Dev_VidEnable(TRUE);
sysPanicing = TRUE;
DBG_CALL;
Dev_SyslogDebug(FALSE);
}
}
/*
* ----------------------------------------------------------------------------
*
* Sys_Printf --
*
* Perform a C style printf except for floating point.
* Enterrupts are disabled during the printf to the console.
* Sys_UnSafePrintf should be used instead if that's undesirable.
*
* Results:
* None.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
/*VARARGS1*/
void
Sys_UnSafePrintf(format, args)
char *format;
int args;
{
(void) Sys_DoPrintf(format, (char *) &args);
}
/*VARARGS1*/
void
Sys_Printf(format, args)
char *format;
int args;
{
DISABLE_INTR();
(void) Sys_DoPrintf(format, (char *) &args);
ENABLE_INTR();
}
/*
* ----------------------------------------------------------------------------
*
* Sys_SafePrintf --
*
* Perform a C style printf except for floating point.
* Interrupts are disabled while printing.
*
* Results:
* None.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
/*VARARGS1*/
void
Sys_SafePrintf(format, args)
char *format;
int args;
{
DISABLE_INTR();
(void) Sys_DoPrintf(format, (char *) &args);
ENABLE_INTR();
}